package com.aplink.dellcommercial.webservices;

import com.aplink.dellcommercial.configuration.DellController;
import com.aplink.dellcommercial.util.DellCommercialUtility;
import com.aplink.dellcommercial.webservices.ServiceConstants.ForgetPasswordService;
import com.aplink.dellcommercial.webservices.ServiceConstants.LoginService;
import com.aplink.generic.constant.SqlDataType;
import com.aplink.generic.pojo.GenericAttribute;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.util.Utility;
import com.aplink.generic.util.convertcount.GenericConverter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.util.ArrayList;

public class WebserviceParserDataHelper {
    private volatile static WebserviceParserDataHelper sInstance = null;

    private ArrayList<ObjPropInfo> mObjPropInfos;

    public static WebserviceParserDataHelper getInstance() {
        if ( sInstance == null ) {
            synchronized ( WebserviceParserDataHelper.class ) {
                if ( sInstance == null ) {
                    sInstance = new WebserviceParserDataHelper();
                }
            }
        }
        return sInstance;
    }

    private DataResult parseLogin( JSONArray jsonarray, MethodParams methodparams )
            throws ParseException, JSONException {
        final DataResult dataResult = new DataResult();
        dataResult.setMethodParam( methodparams );
        final JSONObject jsonResult = (JSONObject) jsonarray.get( 0 );
        if ( jsonResult != null ) {
            final int loginResult = jsonResult
                    .getInt( LoginService.RESULT_ELEMENT );
            if ( loginResult == LoginService.LOGIN_SUCCESS ) {
                final GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );
                for ( final ObjPropInfo info : this.mObjPropInfos ) {
                    if ( jsonResult.has( info.getPropertyName() ) ) {
                        final String value = jsonResult.getString( info
                                .getPropertyName() );
                        final GenericAttribute<String, String> genericAttribute = new GenericAttribute<String, String>(
                                info.getObjectProperty(), value );
                        genericObject.getAttributeList().add( genericAttribute );
                    }
                }
                DellCommercialUtility.checkExpireDay( jsonResult
                        .getString( "TokenExpiryDate" ) );
                final String accountToken = jsonResult
                        .getString( LoginService.TOKEN_ELEMENT );
                final String contactId = jsonResult
                        .getString( LoginService.CONTACT_ID_ELEMENT );
                DellController.getInstance().setAccountToken( accountToken );
                DellController.getInstance().setContactID( contactId );

                genericObject.getAttributeList().addAll(
                        DellCommercialUtility.getExpireDay( jsonResult
                                .getString( LoginService.EXPIRY_DATE_ELEMENT ) ) );

                dataResult.setData( genericObject );
            } else if ( loginResult == LoginService.SET_NEW_PASSWORD ) {
                final String token = jsonResult
                        .getString( LoginService.TOKEN_ELEMENT );
                DellController.getInstance().setAccountToken( token );
            }
        }
        return dataResult;
    }

    private DataResult parsePromotion( JSONArray jsonArray,
                                       MethodParams methodParams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );

                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    String attributeName = null;
                    if ( objPropInfo.getFKeyID() != null ) {
                        if ( objPropInfo.isFKey()
                                && objPropInfo.getPrimaryObjectMapping() != null ) {
                            attributeName = objPropInfo.getFKeyID();
                        }
                    } else {
                        attributeName = objPropInfo.getPropertyName();
                    }

                    SqlDataType dataType = objPropInfo.getDataType();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( attributeName ) ) {
                        String value = jsonResult.get( attributeName ).toString();
                        attribute = GenericConverter.getGenericAttribute(
                                objPropInfo.getObjectProperty(), dataType,
                                value );
                    } else {
                        attribute = GenericConverter
                                .getGenericAttribute(
                                        objPropInfo.getObjectProperty(),
                                        dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                genericObjects.add( genericObject );
            }
        }
        result.setData( genericObjects );
        return result;
    }

    private DataResult parsePriceBook( JSONArray jsonArray,
                                       MethodParams methodParams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );

                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    SqlDataType dataType = objPropInfo.getDataType();
                    String name = objPropInfo.getObjectProperty();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( objPropInfo.getPropertyName() ) ) {
                        String value = jsonResult.get(
                                objPropInfo.getPropertyName() ).toString();
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, value );
                    } else {
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                genericObjects.add( genericObject );
            }
        }
        result.setData( genericObjects );
        return result;
    }

    private DataResult parseProduct( JSONArray jsonArray,
                                     MethodParams methodParams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );

                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    SqlDataType dataType = objPropInfo.getDataType();
                    String name = objPropInfo.getObjectProperty();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( objPropInfo.getPropertyName() ) ) {
                        String value = jsonResult.get(
                                objPropInfo.getPropertyName() ).toString();
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, value );
                    } else {
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                genericObjects.add( genericObject );
            }
        }
        result.setData( genericObjects );
        return result;
    }

    private DataResult parseTips( JSONArray jsonArray, MethodParams methodParams )
            throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
        String currentDatetime = Utility.getDateTime();
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );
                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    SqlDataType dataType = objPropInfo.getDataType();
                    String name = objPropInfo.getObjectProperty();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( objPropInfo.getPropertyName() ) ) {
                        String value = jsonResult.get(
                                objPropInfo.getPropertyName() ).toString();
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, value );
                    } else {
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                genericObject.setContentByAttributeName( "DownloadedTime",
                        currentDatetime );
                genericObjects.add( genericObject );
            }
        }
        result.setData( genericObjects );
        return result;
    }

    private DataResult parseTipDetail( JSONArray jsonArray,
                                       MethodParams methodParams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );
                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    SqlDataType dataType = objPropInfo.getDataType();
                    String name = objPropInfo.getObjectProperty();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( objPropInfo.getPropertyName() ) ) {
                        String value = jsonResult.get(
                                objPropInfo.getPropertyName() ).toString();
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, value );
                    } else {
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                result.setData( genericObject );
            }
        }
        return result;
    }

    private DataResult parseJson( JSONArray jsonArray, MethodParams methodParams )
            throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodParams );
        ArrayList<GenericObject> genericObjects = new ArrayList<GenericObject>();
        for ( int i = 0 ; i < jsonArray.length() ; i++ ) {
            JSONObject jsonResult = (JSONObject) jsonArray.get( i );
            if ( jsonResult != null ) {
                GenericObject genericObject = new GenericObject();
                genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                        .getObjectMapping() );
                for ( ObjPropInfo objPropInfo : this.mObjPropInfos ) {
                    SqlDataType dataType = objPropInfo.getDataType();
                    String name = objPropInfo.getObjectProperty();
                    GenericAttribute<?, ?> attribute;
                    if ( jsonResult.has( objPropInfo.getPropertyName() ) ) {
                        String value = jsonResult.get(
                                objPropInfo.getPropertyName() ).toString();
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, value );
                    } else {
                        attribute = GenericConverter.getGenericAttribute( name,
                                dataType, null );
                    }
                    genericObject.getAttributeList().add( attribute );
                }
                genericObjects.add( genericObject );
            }
        }
        result.setData( genericObjects );
        return result;
    }

    private DataResult parseResetPassword( JSONArray jsonarray,
                                           MethodParams methodparams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodparams );
        final JSONObject jsonResult = (JSONObject) jsonarray.get( 0 );
        if ( jsonResult != null ) {
            final String resetPasswordResult = jsonResult
                    .getString( ForgetPasswordService.RESULT_ELEMENT );
            result.setData( resetPasswordResult );
        }
        return result;
    }

    private DataResult parseUserProfile( JSONArray jsonarray,
                                         MethodParams methodparams ) throws JSONException {
        final DataResult result = new DataResult();
        result.setMethodParam( methodparams );
        final GenericObject genericObject = new GenericObject();
        final JSONObject jsonResult = (JSONObject) jsonarray.get( 0 );
        genericObject.setObjectMappingName( this.mObjPropInfos.get( 0 )
                .getObjectMapping() );
        for ( final ObjPropInfo info : this.mObjPropInfos ) {
            if ( jsonResult.has( info.getObjectProperty() ) ) {
                String value = jsonResult.getString( info.getPropertyName() );
                if ( value.equalsIgnoreCase( "null" ) ) {
                    value = " ";
                }
                final GenericAttribute<String, String> genericAttribute = new GenericAttribute<String, String>(
                        info.getObjectProperty(), value );
                genericObject.getAttributeList().add( genericAttribute );
                if ( info.isAccountId() ) {
                    DellController.getInstance().setAccountEmail( value );
                }
            }
        }
        result.setData( genericObject );

        return result;
    }

    private DataResult parseChangePassword( JSONArray jsonarray,
                                            MethodParams methodparams ) throws JSONException {
        DataResult result = new DataResult();
        result.setMethodParam( methodparams );
        JSONObject jsonResult = (JSONObject) jsonarray.get( 0 );
        if ( jsonResult != null ) {
            int code = jsonResult.getInt( "Result" );
            result.setData( code );
        }
        return result;
    }

    public DataResult parse( String data, MethodParams methodparam,
                             ArrayList<ObjPropInfo> objPropInfos ) throws JSONException,
            ParseException {
        if ( data == null ) {
            return null;
        }
        if ( data.trim().startsWith( "{" ) ) {
            data = String.format( "[%s]", data.trim() );
        }
        this.mObjPropInfos = objPropInfos;
        final JSONArray jsonarray = new JSONArray( data );
        switch ( methodparam.getName() ) {
            case LOGIN:
                return this.parseLogin( jsonarray, methodparam );
            case GET_CUSTOMER_INFO:
                return this.parseUserProfile( jsonarray, methodparam );
            case resetPass:
                return this.parseResetPassword( jsonarray, methodparam );
            case GET_PROMOTION:
                return this.parsePromotion( jsonarray, methodparam );
            case GET_PRICEBOOK:
                return this.parsePriceBook( jsonarray, methodparam );
            case GET_PRODUCT:
                return this.parseProduct( jsonarray, methodparam );
            case CHANGE_PASSWORD:
                return this.parseChangePassword( jsonarray, methodparam );
            case GET_ALL_TIP:
                return this.parseTips( jsonarray, methodparam );
            case GET_TIP_DETAIL:
                return this.parseTipDetail( jsonarray, methodparam );
            case GET_ALL_QUIZ:
                return this.parseJson( jsonarray, methodparam );
            default:
                break;
        }
        return null;
    }
}
